﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.ApplicationModel.Background;
using Windows.Devices.Bluetooth;
using Windows.Devices.Bluetooth.Advertisement;
using Windows.Devices.Enumeration;
using Windows.Storage.Streams;

namespace MyHelloWinDevice
{
    public class BluetoothContext
    {
        public BluetoothContext(DeviceInformation deviceInfoIn)
        {
            DeviceInformation = deviceInfoIn;
        }

        public DeviceInformation DeviceInformation { get; private set; }

        public string Id => DeviceInformation.Id;
        public string Name => DeviceInformation.Name;
        public bool IsPaired => DeviceInformation.Pairing.IsPaired;
        public bool IsConnected => (bool?)DeviceInformation.Properties["System.Devices.Aep.IsConnected"] == true;

        public IReadOnlyDictionary<string, object> Properties => DeviceInformation.Properties;
        
        public void Update(DeviceInformationUpdate deviceInfoUpdate)
        {
            DeviceInformation.Update(deviceInfoUpdate);
        }
    }

    class Bluetooth
    {
        static public string g_strTaskPostName = "_BlueTooth";

        private List<BluetoothContext> m_BlueToothDeviceList = new List<BluetoothContext>();
        private DeviceWatcher m_deviceWatcher;
        private CDeviceManger m_Parent = null;

        public Boolean RegistMonitor(CDeviceManger Parent)
        {
            m_Parent = Parent;
            string[] requestedProperties = { "System.Devices.Aep.DeviceAddress", "System.Devices.Aep.IsConnected" };
            m_deviceWatcher = DeviceInformation.CreateWatcher("(System.Devices.Aep.ProtocolId:=\"{bb7bb05e-5972-42b5-94fc-76eaa7084d49}\")",
            //m_deviceWatcher = DeviceInformation.CreateWatcher("(System.Devices.Aep.ProtocolId:=\"{e0cbf06c-cd8b-4647-bb8a-263b43f0f974}\")",
                                                                requestedProperties,
                                                              DeviceInformationKind.AssociationEndpoint);

            m_deviceWatcher.Added += DeviceWatcher_Added;
            m_deviceWatcher.Updated += DeviceWatcher_Updated;
            m_deviceWatcher.Removed += DeviceWatcher_Removed;
            m_deviceWatcher.EnumerationCompleted += DeviceWatcher_EnumerationCompleted;
            m_deviceWatcher.Stopped += DeviceWatcher_Stopped;

            m_deviceWatcher.Start();

            return true;
        }

        public Boolean StopMonitor()
        {
            if (m_deviceWatcher != null)
            {
                m_deviceWatcher.Added -= DeviceWatcher_Added;
                m_deviceWatcher.Updated -= DeviceWatcher_Updated;
                m_deviceWatcher.Removed -= DeviceWatcher_Removed;
                m_deviceWatcher.EnumerationCompleted -= DeviceWatcher_EnumerationCompleted;
                m_deviceWatcher.Stopped -= DeviceWatcher_Stopped;

                m_deviceWatcher.Stop();
                m_deviceWatcher = null;
            }
            return false;
        }

        public Boolean RegistMonitor(CDeviceManger Parent, string strTaskPerName, string strEntryPoint)
        {
            m_Parent = Parent;
            string[] requestedProperties = { "System.Devices.Aep.DeviceAddress", "System.Devices.Aep.IsConnected" };
            DeviceWatcherEventKind[] triggerEventKinds = { DeviceWatcherEventKind.Add, DeviceWatcherEventKind.Remove, DeviceWatcherEventKind.Update };
            DeviceWatcher deviceWatcher = null;
            deviceWatcher = DeviceInformation.CreateWatcher("(System.Devices.Aep.ProtocolId:=\"{e0cbf06c-cd8b-4647-bb8a-263b43f0f974}\")",
                                                            requestedProperties,
                                                            DeviceInformationKind.AssociationEndpoint);

            DeviceWatcherTrigger deviceWatcherTrigger = deviceWatcher.GetBackgroundTrigger(triggerEventKinds);

            BackgroundTaskBuilder taskBuilder;
            taskBuilder = new BackgroundTaskBuilder();
            taskBuilder.Name = strTaskPerName + g_strTaskPostName;
            taskBuilder.TaskEntryPoint = strEntryPoint;
            taskBuilder.SetTrigger(deviceWatcherTrigger);
            BackgroundTaskRegistration backgroundTaskRegistration = taskBuilder.Register();

            return true;
        }

        public Boolean ClearMonitor(string strPerName)
        {
            string strTaskName = String.Format("{0}_BlueTooth", strPerName);
            foreach (var task in BackgroundTaskRegistration.AllTasks)
            {
                if (strTaskName == task.Value.Name)
                {
                    task.Value.Unregister(true);
                }
            }

            return true;
        }

        public void DealWithMonitor(CDeviceManger Parent, IBackgroundTaskInstance taskInstance)
        {
            m_Parent = Parent;
            DeviceWatcherTriggerDetails TriggerDetails = (DeviceWatcherTriggerDetails)taskInstance.TriggerDetails;

            foreach (DeviceWatcherEvent e in TriggerDetails.DeviceWatcherEvents)
            {
                switch (e.Kind)
                {
                    case DeviceWatcherEventKind.Add:
                        {
                            DeviceInformation deviceInfo = e.DeviceInformation;
                            if (FindBluetoothDevice(deviceInfo.Id) == null && deviceInfo.Name != string.Empty && m_Parent != null)
                            {
                                // 添加设备
                                m_BlueToothDeviceList.Add(new BluetoothContext(deviceInfo));
                            }

                        }
                        break;

                    case DeviceWatcherEventKind.Update:
                        {
                            // 更新设备
                            DeviceInformationUpdate deviceInfoUpdate = e.DeviceInformationUpdate;
                            BluetoothContext bleDeviceDisplay = FindBluetoothDevice(deviceInfoUpdate.Id);
                            if (bleDeviceDisplay != null)
                            {
                                bleDeviceDisplay.Update(deviceInfoUpdate);
                            }
                        }
                        break;

                    case DeviceWatcherEventKind.Remove:
                        {
                            DeviceInformationUpdate deviceInfoUpdate = e.DeviceInformationUpdate;
                            BluetoothContext bleDeviceDisplay = FindBluetoothDevice(deviceInfoUpdate.Id);
                            if (bleDeviceDisplay != null)
                            {
                                m_BlueToothDeviceList.Remove(bleDeviceDisplay);
                            }
                        }
                        break;
                }
            };
        }

        public int VeiwAllDevicesWithTask()
        {
            int rv = 0;
            foreach (BluetoothContext DeviceItem in m_BlueToothDeviceList)
            {
                DeviceContext Context = new DeviceContext();
                Context.Type = DeviceType.BlueTooth;
                Context.DeviceID = DeviceItem.Id;
                Context.DeviceName = DeviceItem.Name;
                Context.IsConnected = DeviceItem.IsConnected;
                m_Parent.AddEvent(Context);
                rv++;
            }
            return rv;
        }
        
        public Boolean GetKey(DeviceContext Driver, out IBuffer deviceKey, out IBuffer authKey)
        {
            deviceKey = null;
            authKey = null;

            return false;
        }

        private BluetoothContext FindBluetoothDevice(string strID)
        {

            // 过滤去蓝牙设备
            foreach (BluetoothContext DeviceItem in m_BlueToothDeviceList)
            {
                if (DeviceItem.Id == strID)
                {
                    return DeviceItem;
                }
            }
            return null;
        }

        private void DeviceWatcher_Added(DeviceWatcher Sender, DeviceInformation DeviceInfo)
        {
            if (FindBluetoothDevice(DeviceInfo.Id) == null && DeviceInfo.Name != string.Empty && m_Parent != null)
            {
                // 添加设备
                BluetoothContext tmp = new BluetoothContext(DeviceInfo);
                m_BlueToothDeviceList.Add(tmp);

                DeviceContext Context = new DeviceContext();
                Context.Type = DeviceType.BlueTooth;
                Context.DeviceID = DeviceInfo.Id;
                Context.DeviceName = DeviceInfo.Name;
                Context.IsConnected = tmp.IsConnected;
                m_Parent.AddEvent(Context);
            }
        }

        private void DeviceWatcher_Updated(DeviceWatcher Sender, DeviceInformationUpdate DeviceInfoUpdate)
        {
            if (m_Parent != null)
            {
                // 更新设备
                BluetoothContext bleDeviceDisplay = FindBluetoothDevice(DeviceInfoUpdate.Id);
                if (bleDeviceDisplay != null)
                {
                    bleDeviceDisplay.Update(DeviceInfoUpdate);
                    DeviceContext Context = new DeviceContext();
                    Context.Type = DeviceType.BlueTooth;
                    Context.DeviceID = DeviceInfoUpdate.Id;
                    Context.DeviceName = bleDeviceDisplay.Name;
                    Context.IsConnected = bleDeviceDisplay.IsConnected;
                    m_Parent.UpdateEvent(Context);
                }
           }
        }

        private void DeviceWatcher_Removed(DeviceWatcher Sender, DeviceInformationUpdate DeviceInfoUpdate)
        {
            if (m_Parent != null)
            {
                // 删除设备
                BluetoothContext bleDeviceDisplay = FindBluetoothDevice(DeviceInfoUpdate.Id);
                if (bleDeviceDisplay != null)
                {
                    m_BlueToothDeviceList.Remove(bleDeviceDisplay);
                }

                DeviceContext Context = new DeviceContext();
                Context.Type = DeviceType.BlueTooth;
                Context.DeviceID = DeviceInfoUpdate.Id;
                m_Parent.RemoveEvent(Context);
            }
        }

        private void DeviceWatcher_EnumerationCompleted(DeviceWatcher Sender, object e)
        {
            if (m_Parent != null)
            {
                DeviceContext Context = new DeviceContext();
                Context.Type = DeviceType.BlueTooth;
                m_Parent.CompleteEvent(Context);
            }
        }

        private void DeviceWatcher_Stopped(DeviceWatcher Sender, object e)
        {
            if (m_Parent != null)
            {
                DeviceContext Context = new DeviceContext();
                Context.Type = DeviceType.BlueTooth;
                m_Parent.StopEvent(Context);
            }
        }
    }
}
